﻿using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace EasyDDD.AdminModule.Application.CommandsSysAdmin
{
    public record SysAdminLoginCommand : ICommand<SysAdminLoginCommandResult>
    {
        public string UserName { get; set; } = default!;
        public string Password { get; set; } = default!;
    }

    public record SysAdminLoginCommandResult
    {
        public string avatar { get; set; } = default!;
        public string username { get; set; } = default!;
        public string nickname { get; set; } = default!;
        public string[] roles { get; set; } = default!;
        public string[] permissions { get; set; } = default!;
        public string accessToken { get; set; } = default!;
        public string refreshToken { get; set; } = default!;
        public DateTime expires { get; set; } = default!;
    }

    public class SysAdminLoginCommandHandler(
        //IMapper mapper,
        IConfiguration configuration,
        Repository.SysAdminRepository repository,
        Records.SysAdminRoleRecords sysAdminRoleRecords,
        ILogger<SysAdminCreateCommandHandler> logger)
        : ICommandHandler<SysAdminLoginCommand, SysAdminLoginCommandResult>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<SysAdminLoginCommandResult> Handle(SysAdminLoginCommand request, CancellationToken cancellationToken)
        {
            //TODO: 回头再优化
            logger.LogDebug("命令 SysAdminLoginCommandHandler");
            var entity = await repository.GetWithUserRoles(request.UserName);
            if (entity == null)
            {
                throw new BusinessException("账号不存在，请检查账号密码");
            }
            if (entity.IsLockout())
            {
                throw new BusinessException("该账号已被锁定，请稍后再试");
            }
            if (!entity.ComparePassword(request.Password))
            {
                entity.LoginFail();
                throw new BusinessException("登录失败，请检查账号密码");
            }
            entity.LoginSuccess();

            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.NameIdentifier, entity.Id.ToString()));
            claims.Add(new Claim(ClaimTypes.Name, entity.UserName));

            var roleIds = entity.UserRoles.Select(x => x.RoleId).ToArray();
            claims.AddRange(await sysAdminRoleRecords.GetClaims(roleIds));

            #region JWT
            var secret = configuration["JWT:Secret"]!;
            var expires = Convert.ToDouble(configuration["JWT:Expires"]!);
            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
            var algorithm = SecurityAlgorithms.HmacSha256;
            var signingCredentials = new SigningCredentials(secretKey, algorithm);

            var jwt = new JwtSecurityToken(
                claims: claims,
                expires: DateTime.Now.AddMinutes(expires),
                signingCredentials: signingCredentials
             );
            var accessToken = new JwtSecurityTokenHandler().WriteToken(jwt); 
            #endregion

            return new SysAdminLoginCommandResult()
            {
                accessToken = accessToken,
                avatar = "",
                expires = DateTime.Now.AddMinutes(expires),
                nickname = entity.NickName,
                permissions = claims.Where(e => e.Type == ClaimTypes.MenuPermissions).Select(e => e.Value).ToArray(),
                refreshToken = "",
                roles = claims.Where(e => e.Type == ClaimTypes.Role).Select(e => e.Value).ToArray(),
                username = entity.UserName
            };
        }
    }
}
